#pragma once

#include "SimpleLogger.h"

namespace RoomFW {

class WindowsUtility
{
public:
	static WindowsUtility& Instance();
	void Lock(void);		// Use lock class below.
	void Unlock(void);
	static std::string LastErrorString(DWORD lastError);
	void ParseCommandLine(std::vector<std::string>& args);
	static DWORD DiffTickCount(DWORD start);
	static int rand(int min, int max);
	static void logMemoryUsage();

private:
	WindowsUtility(void);
	~WindowsUtility();
	CRITICAL_SECTION CS_;
};

struct WindowsUtilityLock
{
	WindowsUtilityLock(void);
	~WindowsUtilityLock();
};

// Naming hasn't kept pace with implementation, but always log api errors.
//
#define LAST_ERROR_TO_CERR 1

#if LAST_ERROR_TO_CERR
#define SHOW_LAST_ERROR(flag, method, call) \
	if (!(flag)) \
	{ \
		DWORD lastError = ::GetLastError(); \
		G_LOG_4_ERROR("%s %s %i:%s", (method), (call), lastError, RoomFW::WindowsUtility::Instance().LastErrorString(lastError).c_str()); \
	}
#else
#define SHOW_LAST_ERROR(flag, method, call)
#endif

#if LAST_ERROR_TO_CERR
#define SHOW_ERROR(method, call, error) \
{ \
	G_LOG_3_ERROR("%s %s %i", (method), (call), (error)); \
}
#else
#define SHOW_ERROR(method, call, error)
#endif

#if LAST_ERROR_TO_CERR
#define SHOW_ERRNO(flag, method, call) \
	if (!(flag)) \
	{ \
		errno_t err = _get_errno(&err); \
		SHOW_ERROR((method), (call), err); \
	}
#else
#define SHOW_ERRNO(flag, method, call)
#endif

#if LAST_ERROR_TO_CERR
#define SHOW_SOCKET_ERROR(flag, method, call) \
	SHOW_LAST_ERROR((flag), (method), (call));
#else
#define SHOW_SOCKET_ERROR(flag, method, call)
#endif

}
